/*
 * Userdatabase.cpp
 *
 *  Created on: Jun 10, 2011
 *      Author: Mario Hock
 */

#include "Userdatabase.h"

using namespace std;

Userdatabase::Userdatabase()
{
}

Userdatabase::~Userdatabase()
{
}

UserPtr Userdatabase::getUser(string name)
{
    UserMap::iterator it;

    it = database.find(name);

    // name not found
    if ( it == database.end() )
        return NO_USER;

    return it->second;
}

UserPtr Userdatabase::getUser(NodeID id)
{
    IdUserMap::iterator it;

    it = id_database.find(id);

    // name not found
    if ( it == id_database.end() )
        return NO_USER;

    return it->second;
}


UserPtr Userdatabase::createUser(string name)
{
    UserPtr u = User::createUser(name);
    insert(u);

    return u;
}


UserPtr Userdatabase::createTempUser(ariba::NodeID id)
{
    UserPtr u = User::createUser(id);
    id_database.insert( std::pair<NodeID, UserPtr>(u->get_id(), u) );

    return u;
}

void Userdatabase::dropTempUser(UserPtr tempuser)
{
    if ( tempuser->is_temporal() )
    {
        id_database.erase(tempuser->get_id());
    }
}


bool Userdatabase::acceptTempUser(UserPtr tempuser, string name)
{
    if ( tempuser && tempuser->set_name(name) )
    {
        database.insert( std::pair<string, UserPtr>(tempuser->get_name(), tempuser) );
        return true;
    }

    return false;
}



void Userdatabase::insert(UserPtr ptr)
{
    // TODO, hier wird abgefangen, wenn ein neuer user einen alten überschreiben will.. andererseits ist das defaultverhalten erstmal ganz gut, dass einfach der bleibt wie er ist, basta.
    database.insert( std::pair<string, UserPtr>(ptr->get_name(), ptr) );
    id_database.insert( std::pair<NodeID, UserPtr>(ptr->get_id(), ptr) );
}



string Userdatabase::list()
{
    ptree pt;
    UserMap::iterator it;

    // for all users
    for ( it=database.begin() ; it != database.end(); it++ )
    {
        if ( !it->second->is_temporal() )
        {
            ptree pt_u;
            it->second->info(pt_u);
            pt.add_child("user", pt_u);
        }
    }

    ptree pt_top;
    pt_top.add_child("users", pt);
    ostringstream out;
    boost::property_tree::write_xml(out, pt_top);
    return out.str();
}


string Userdatabase::list_old()
{
    UserMap::iterator it;
    stringstream s;

    // show content:
    for ( it=database.begin() ; it != database.end(); it++ )
    {
        if ( it->second->is_connected() )
            s << "* ";
        else if ( it->second->connection_pending() )
            s << "x ";

        s << it->first /*<< " => " << it->second->get_id()*/ << endl;
    }

    return s.str();
}


void Userdatabase::set_myself(UserPtr I)
{
    myself = I;
}

// TODO exception wenn !myself ?
UserPtr Userdatabase::get_myself()
{
    return myself;
}

Userdatabase::UserMap Userdatabase::get_whole_database()
{
    return database;
}

shared_ptr<ptree> Userdatabase::save()
{
    shared_ptr<ptree> pt(new ptree());
    UserMap::iterator it;

    // for all users
    for ( it=database.begin() ; it != database.end(); it++ )
    {
        if ( !it->second->is_temporal() )
        {
            pt->add_child("user", *it->second->save());
        }
    }

    return pt;
}

void Userdatabase::load(ptree &pt)
{
//    cout << "+++ loading userdatabase" << endl;
    BOOST_FOREACH(ptree::value_type &v, pt)
    {
      UserPtr u = User::createUser(v.second);
//      cout << "+++ insert" << u->get_name() << endl;
      insert(u);
    }

//    cout << "+++ loading userdatabase [DONE]" << endl;
}
